package org.framework.lazy.cloud.network.heartbeat.protocol.actuator;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.http.FullHttpRequest;
import org.framework.lazy.cloud.network.heartbeat.common.decoder.TransferDecoder;
import org.framework.lazy.cloud.network.heartbeat.common.encoder.TransferEncoder;
import org.framework.lazy.cloud.network.heartbeat.common.utils.ChannelAttributeKeyUtils;
import org.framework.lazy.cloud.network.heartbeat.protocol.handler.NettyHttpProxyBackendHandler;
import org.framework.lazy.cloud.network.heartbeat.protocol.route.RouteContext;
import org.wu.framework.core.utils.ObjectUtils;

/**
 * 默认 http 代理处理器
 */
public class DefaultNettyHttpProxyActuator extends AbstractNettyHttpProxyActuator {
    /**
     * 是否允许代理
     *
     * @param host 访问主机地址
     * @param port 访问端口
     */
    @Override
    public boolean support(String host, int port) {
        return ObjectUtils.isNotEmpty(RouteContext.getRoute(host, String.valueOf(port)));
    }

    /**
     * 获取代理通道
     *
     * @param originChannel   原始通道
     * @param fullHttpRequest 消息体
     * @param host            访问主机地址
     * @param port            访问端口
     */
    @Override
    public Channel createProxyChannelThenSend(Channel originChannel, FullHttpRequest fullHttpRequest, String host, int port) {
        Bootstrap b = new Bootstrap();
        b.group(originChannel.eventLoop())
                .channel(NioSocketChannel.class)
                .handler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    protected void initChannel(SocketChannel ch) throws Exception {
                        ch.pipeline().addLast(
                                new TransferDecoder(Integer.MAX_VALUE, 1024 * 1024 * 10),
                                new TransferEncoder(),
                                new NettyHttpProxyBackendHandler()
                        );
                    }
                });
        ChannelFuture f = b.connect(host, port);
        Channel proxyChannel = f.channel();
        f.addListener((ChannelFutureListener) future -> {
            if (future.isSuccess()) {
                ChannelAttributeKeyUtils.buildNextChannel(proxyChannel, originChannel);
                ChannelAttributeKeyUtils.buildNextChannel(originChannel, proxyChannel);
                doSend(proxyChannel, fullHttpRequest);
            } else {
                originChannel.close();
            }
        });
        return proxyChannel;
    }


}
